#!/usr/bin/python

import pygame
import Entity
import game_engine.GameEngine

# An entity class that has some movement logic
class MoveableEntity(Entity.Entity):

    # Obvious
    def __init__(self, name):
        super(MoveableEntity, self).__init__(name)
        self.m_pixelRateX = 0
        self.m_pixelRateY = 0
        self.m_followPath = []
        self.m_nextPathStepTime = 0
        self.m_pathTimePerMove = 0

        

    # Update for each frame
    def frameUpdate(self, elapsedms, absolutems):

        # Call base class
        super(MoveableEntity, self).frameUpdate(elapsedms, absolutems)

        # Path follow logic
        if len(self.m_followPath) > 0:
            if (absolutems > self.m_nextPathStepTime):
                self.m_nextPathStepTime = absolutems + self.m_pathTimePerMove
                nextTile = self.m_followPath.pop()
                self.tryWarpTo(nextTile[0], nextTile[1], self.m_pathTimePerMove)


        # Do per-frame movement if needed
        if (self.m_pixelRateX != 0 or self.m_pixelRateY != 0):
            self.m_pixelOffsetX += self.m_pixelRateX * elapsedms
            self.m_pixelOffsetY += self.m_pixelRateY * elapsedms
            # If values have the same sign, then we've crossed 0
            if self.m_pixelRateX != 0 and self.m_pixelRateX * self.m_pixelOffsetX > 0:
                self.m_pixelRateX=0
                self.m_pixelOffsetX=0
            if self.m_pixelRateY != 0 and self.m_pixelRateY * self.m_pixelOffsetY > 0:
                self.m_pixelRateY=0
                self.m_pixelOffsetY=0

    # Force Player to Stand
    def stand(self):
        self.m_standing = True

    # Called when this entity attempts to interact with another entity by bumping into it
    def interactBump(self, otherEntity):
        return False

    # Attempts to follow a provided path
    def tryFollowPath(self, reversePath, timePerMovement):
        self.m_followPath=reversePath
        self.m_pathTimePerMove = timePerMovement

    # Stop pathing
    def stopPath(self):
        self.m_followPath = []

    # Try to move this object in the direction specified
    def tryMove(self, x, y, timeToMovems):
        # If there's any current path, clear it
        if len(self.m_followPath) > 0:
            del self.m_followPath[:]

        # Call through to warp
        return self.tryWarpTo(self.m_positionX + x, self.m_positionY + y, timeToMovems)


    # Try to move this object to the tile specified (note that the object will not cross the intervening tiles!)
    def tryWarpTo(self, newX, newY, timeToMovems):

        # Check map allowed entry into this grid
        levelManager = game_engine.GameEngine.getGameEngine().getLevelManager()
        if not(levelManager.isEntityWalkable(self, newX, newY)):
            print "Cannot walk to "+str(newX)+","+str(newY)+" due to map."
            return False

        # Collision check with other entities
        (canMove, whoBlocks) = levelManager.getEntityCollisionMap().canEntityMoveTo(self, (newX, newY))
        if not(canMove):
            print "Cannot walk to "+str(newX)+","+str(newY)+" due to entity."
            # If we can't move here, handle running into the other entity
            self.interactBump(whoBlocks)
            whoBlocks.interactBumped(self)
            return False

        # Move on collision map
        levelManager.getEntityCollisionMap().moveEntity(self, (newX, newY))

        # Calculate deltas
        deltaX = newX - self.m_positionX
        deltaY = newY - self.m_positionY

        self.m_standing = False
        if deltaX > 0:
            self.m_direction = "right"
        elif deltaX < 0:
            self.m_direction = "left"
        elif deltaY > 0:
            self.m_direction = "down"
        elif deltaY < 0:
            self.m_direction = "up"
        
        # Update our position
        self.setPosition(newX, newY)


        # Set pixel offset so that we smoothly transition over the movement time period
        self.m_pixelOffsetX = -(deltaX * self.m_tileSize)
        self.m_pixelOffsetY = -(deltaY * self.m_tileSize)
        self.m_pixelRateX = (deltaX * self.m_tileSize) / float(timeToMovems)
        self.m_pixelRateY = (deltaY * self.m_tileSize) / float(timeToMovems)


        return True

